#pragma once

template<class tRet>
class BaseFunctor0Arg
{
public:
	virtual ~BaseFunctor0Arg() {}
	virtual tRet operator() () = 0;
};

template<class tRet=void>
class GlobalFunctor0Arg : public BaseFunctor0Arg<tRet>
{
public:
	typedef tRet (*FUNC)();
	GlobalFunctor0Arg(FUNC func) : m_func(func) {}
	virtual ~GlobalFunctor0Arg() {}

	virtual tRet operator() ()
	{
		if( m_func )
			return m_func();
		return tRet(0);
	}

protected:
	FUNC m_func;
};


template <class Ty,class tRet=void>
class MemberFunctor0Arg :  public BaseFunctor0Arg<tRet>
{
public:
	typedef tRet (Ty::*FUNC)();
	MemberFunctor0Arg(Ty*obj,FUNC func) : m_object(obj),m_func(func) {}
	virtual ~MemberFunctor0Arg() {}

	virtual tRet operator() ()
	{
		if( m_func && m_object )
			return (m_object->*m_func)();
		return tRet(0);
	}

protected:
	FUNC m_func;
	Ty*	 m_object;
};


template<class Arg1,class tRet>
class BaseFunctor1Arg
{
public:
	virtual ~BaseFunctor1Arg() {}
	virtual tRet operator() (Arg1 arg) = 0;
};

template<class Arg1,class tRet=void>
class GlobalFunctor1Arg : public BaseFunctor1Arg<Arg1,tRet>
{
public:
	typedef tRet (*FUNC)(Arg1);
	GlobalFunctor1Arg(FUNC func) : m_func(func) {}
	virtual ~GlobalFunctor1Arg() {}

	virtual tRet operator() (Arg1 arg)
	{
		if( m_func )
			return m_func(arg);
		return tRet(0);
	}

protected:
	FUNC m_func;
};


template <class Ty,class Arg1,class tRet=void>
class MemberFunctor1Arg :  public BaseFunctor1Arg<Arg1,tRet>
{
public:
	typedef tRet (Ty::*FUNC)(Arg1);
	MemberFunctor1Arg(Ty*obj,FUNC func) : m_object(obj),m_func(func) {}
	virtual ~MemberFunctor1Arg() {}

	virtual tRet operator() (Arg1 arg)
	{
		if( m_func && m_object )
			return (m_object->*m_func)(arg);
		return tRet(0);
	}

protected:
	FUNC m_func;
	Ty*	 m_object;
};


template <class tRet>
BaseFunctor0Arg<tRet>* makefunctor(tRet(*func)())
{
	return new GlobalFunctor0Arg<tRet>(func);
}

template <class Ty,class tRet>
BaseFunctor0Arg<tRet>* makefunctor(Ty* obj,tRet(Ty::*func)())
{
	return new MemberFunctor0Arg<Ty,tRet>(obj,func);
}

template <class Arg1,class tRet>
BaseFunctor1Arg<Arg1,tRet>* makefunctor(tRet(*func)(Arg1))
{
	return new GlobalFunctor1Arg<tRet>(func);
}

template <class Ty,class Arg1,class tRet>
BaseFunctor1Arg<Arg1,tRet>* makefunctor(Ty* obj,tRet(Ty::*func)(Arg1))
{
	return new MemberFunctor1Arg<Ty,Arg1,tRet>(obj,func);
}


template <class tRet>
class EventHandler0Arg
{
public:
	typedef BaseFunctor0Arg<tRet> tListener;
	EventHandler0Arg() : m_listeners(NULL) {}
	~EventHandler0Arg(){ Clear(); }
	
	void operator +=(tListener* lst)
	{
		Add(lst);
		
	}
	void notify()
	{
		if( !m_listeners )	return;
		for( std::vector<tListener*>::iterator iter= m_listeners->begin(); iter != m_listeners->end() ; ++iter )
		{
			tListener* lst = (*iter);
			if( lst )
				lst->operator ()();
		}

	}
	void Add(tListener* lst)
	{
		_Allocate();
		if( lst )
			m_listeners->push_back(lst);
	}
	void Clear()
	{
		if( m_listeners )
		{
			for( std::vector<tListener*>::iterator iter= m_listeners->begin(); iter != m_listeners->end() ; ++iter )
			{
				tListener* lst = (*iter);
				SAFE_DELETE(lst);
			}
			m_listeners->clear();
			delete m_listeners;
			m_listeners = NULL;
		}
	}

protected:
	void _Allocate()
	{
		if( !m_listeners )
			m_listeners = new std::vector<tListener* >();
	}
protected:
	std::vector<tListener* >* m_listeners;
};

template <class Arg1,class tRet>
class EventHandler1Arg
{
public:
	typedef BaseFunctor1Arg<Arg1,tRet> tListener;
	EventHandler1Arg() : m_listeners(NULL) {}
	~EventHandler1Arg()	{	Clear();	}
	
	void operator +=(tListener* lst)
	{
		Add(lst);
		
	}
	void notify(Arg1 arg)
	{
		if( !m_listeners )	return;
		for( std::vector<tListener*>::iterator iter= m_listeners->begin(); iter != m_listeners->end() ; ++iter )
		{
			tListener* lst = (*iter);
			if( lst )
				lst->operator ()(arg);
		}

	}
	void Add(tListener* lst)
	{
		_Allocate();
		if( lst )
			m_listeners->push_back(lst);
	}
	void Clear()
	{
		if( m_listeners )
		{
			for( std::vector<tListener*>::iterator iter= m_listeners->begin(); iter != m_listeners->end() ; ++iter )
			{
				tListener* lst = (*iter);
				SAFE_DELETE(lst);
			}
			m_listeners->clear();
			delete m_listeners;
			m_listeners = NULL;
		}
	}

protected:
	void _Allocate()
	{
		if( !m_listeners )
			m_listeners = new std::vector<tListener* >();
	}
protected:
	std::vector<tListener* >* m_listeners;
};
